<?php

namespace tools\lib\main\model;

use tools\lib\main\Common;

/**
 * 创建logic
 * Class Logic
 * @package app\common\command\create\file
 */
class Logic extends Common
{
    /**
     * @return string
     * @throws \ReflectionException
     */
    public function template()
    {

        $model = preg_replace('/Logic/', 'Model', $this->className());

        $model_namespace = $this->getFileProperties('model_namespace') ?: $this->getFileProperties('namespace');

        if (empty($model_namespace)) {
            return '';
        }

        // 同一目录下,不需要使用use
        if ($this->namespace == $model_namespace) {
            $model_namespace = '';
        } else {
            $model_namespace = 'use ' . $model_namespace . '\\' . $model . ';';
        }

        $template = <<<EOT
<?php

{$this->getFileNamespace()}

{$this->getFileUse()}
$model_namespace

class {$this->className()} {$this->getFileExtends()}
{
    protected \$fields = {$this->transSelectField()};

    /**
     * @return $model|\\think\Model
     */
    protected function model()
    {
        return new $model();
    }
    
    {$this->create()}
    {$this->transAction()}
    {$this->select()}
}
EOT;

        return $template;
    }

    /**
     * @return string
     * @throws \ReflectionException
     */
    public function transAction()
    {
        $template = '' . "\n";

        $columns = tableColumns($this->parameter->getName());

        if ($columns) {
            foreach ($columns as $column) {

                $field = $column['Field'];

                /**
                 * 如果字段中包含name，title等字段信息，则自动追加getName,getTitle信息
                 * 这里是tp中自己封装的一个MainLogic，特定的数据信息，暂时没有优化这里的数据
                 */
                if (in_array($field, ['name', 'title'])) {
                    $template .= $this->getFieldMethods($field);
                }

                /**
                 * 根据常量信息生成transXX()方法信息
                 */
                $constant = $this->transConstant($field);
                if (isSatisfyConstant($column) && $constant) {
                    $action = transToPascal($field);

                    // 对应的变量
                    $param = lcfirst($action);

                    $template .= <<<EOT
    /**
     * @param mixed \${$param}
     * @return array|mixed|string
     */
    public function trans{$action}(\${$param} = null)
    {
        \$data = [{$this->transConstant($field)}
        ];
       
        if (null !== \${$param}) {
            return isset(\$data[\${$param}]) ? \$data[\${$param}] : '';
        }
    
        return \$data;  
    }
EOT;
                    $template .= "\n\n";
                }
            }
        }

        $template = rtrim($template, "\n");

        return $template;
    }

    /**
     * @param $field
     * @return string
     * @throws \ReflectionException
     */
    private function transConstant($field)
    {
        $class_name = preg_replace('/Logic/', 'Constant', $this->className());

        $namespace = $this->getFileProperties('constant_namespace') ?: $this->getFileProperties('namespace');

        if (empty($namespace)) {
            return '';
        }

        $namespace = $namespace . '\\' . $class_name;

        $template = "\n";
        if (class_exists($namespace)) {
            $reflection = new \ReflectionClass($namespace);
            $constants = $reflection->getConstants();
            $field = strtoupper($field);

            $comments = $this->transComment();

            if ($constants) {
                foreach ($constants as $key => $item) {
                    if (preg_match('/^' . $field . '_.+/', $key)) {
                        if (isset($comments[strtolower($key)])) {
                            $comment = $comments[strtolower($key)];
                        } else {
                            $comment = '未知';
                        }

                        $template .= '            '
                            . $class_name . '::' . $key
                            . ' => '
                            . '\''
                            . $comment
                            . '\''
                            . ','
                            . "\n";
                    }
                }
            }
        }

        $template = rtrim($template, "\n");

        return $template;
    }

    /**
     * @return array
     */
    private function transComment()
    {
        $columns = tableColumns($this->parameter->getName());
        $comments = [];
        if ($columns) {
            foreach ($columns as $column) {
                $field_name = $column['Field'];
                $field_type = $column['Type'];
                $field_comment = $column['Comment'];
                if (preg_match('/tinyint/', $field_type)) {
                    /**
                     * 状态  0 不展示 hide 1 展示 show
                     */

                    $field_comment = explode(' ', $field_comment);
                    /**
                     * 过滤空置(注意0值)
                     */
                    $field_comment = array_filter($field_comment, function ($value) {
                        if ($value === '') {
                            return false;
                        }
                        return true;
                    });
                    array_shift($field_comment);
                    $field_comment = array_chunk($field_comment, 3);

                    if ($field_comment) {
                        foreach ($field_comment as $key => $comment) {
                            if (count($comment) != 3 || !preg_match('/^[a-zA-Z]+/', $comment[2])) {
                                break 1;
                            }
                            $description = $comment[1];
                            $name = $comment[2];
                            $comments[$field_name . '_' . $name] = $description;
                        }
                    }
                }
            }
        }

        return $comments;
    }

    /**
     * 数据库表中可以筛选的字段信息
     * @return string
     */
    public function transSelectField()
    {
        $columns = tableColumns($this->parameter->getName());

        $params = [];

        if ($columns) {
            foreach ($columns as $column) {

                $field = $column['Field'];

                if (in_array($field, ['update_time', 'delete_time'])) {
                    continue;
                }

                $params[] = $field;
            }
        }

        return concatArrayFormatNoKey($params);
    }

    /**
     * @param $field
     * @return string
     */
    private function getFieldMethods($field)
    {

        $name = transToPascal($field);

        $template = <<<EOF

    /**
     * @param bool \$withTrashed
     * @return array
     */
    public function get$name(\$withTrashed = false)
    {
        return \$this->setWithTrashed(\$withTrashed)->column('id,$field');
    }

EOF;

        return $template;
    }

    private function create()
    {
        $template = '' . "\n";

        $columns = tableColumns($this->parameter->getName());

        $params = '';

        $data = '' . "\n";

        if ($columns) {
            foreach ($columns as $column) {

                $field = $column['Field'];

                if (in_array($field, ['id', 'update_time', 'create_time', 'delete_time'])) {
                    continue;
                }

                $field = transToUnderline($field);

                $param = '$' . $field . '';

                $params .= $param . ',';

                $data .= '$data[\'' . $field . '\'] = ' . $param . ';' . "\n";
            }
        }

        $validate = transToPascal($this->parameter->getName()) . 'Validate';

        $params = trim($params, ',');

        $template = <<<EOF
    public function create($params)
    {
        $data
        return \$this->setValidate(new {$validate}())->save(\$data);
    }
EOF;
        $template = rtrim($template, "\n");

        return $template;

    }

    private function select()
    {
        $template = '' . "\n";

        $columns = tableColumns($this->parameter->getName());

        if ($columns) {
            foreach ($columns as $column) {

                $field = $column['Field'];

                if (in_array($field, ['id', 'update_time', 'create_time', 'delete_time'])) {
                    continue;
                }

                if (!preg_match('/_id|_no/', $field) && !in_array($field, ['phone'])) {
                    continue;
                }

                $method = transToPascal($field);

                $field = transToUnderline($field);

                $param = '$' . $field . '';

                $template .= <<<EOF
    /**
     * @param $param
     * @return array|bool|null
     */
    public function getBy$method($param)
    {
        if (empty($param)) {
            return false;
        }
        return \$this->setCondition(['$field' => $param])->find();
    }
EOF;
            }
        }


        $template = rtrim($template, "\n");

        return $template;
    }
}